﻿using System;
using System.IO;
using System.ServiceModel;
using System.Threading;

namespace AirlineServer
{
    class Program
    {
        private static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main Thread"; // for logger

            var log = log4net.LogManager.GetLogger(typeof(Program));

            if (args.Length != 6)
            {
                if (log.IsFatalEnabled)
                {
                    log.FatalFormat("Usage: {0} <name> <alliance> <search server port> <airline servers port> " +
                        "<flights search server URI> <input file>", AppDomain.CurrentDomain.FriendlyName);
                }

                return;
            }

            var fdb = new FlightsDatabase();

            try
            {
                if (log.IsInfoEnabled)
                {
                    log.Info("Reading flights from file...");
                }

                var flightsServer = new FlightsServer(args[0], new FileStream(args[5], FileMode.Open, FileAccess.Read, FileShare.Read));
                fdb.AddServer(flightsServer);

                if (log.IsInfoEnabled)
                {
                    log.Info("... OK");
                }
            }
            catch (Exception e)
            {
                if (log.IsFatalEnabled)
                {
                    log.Fatal("... Failed", e);
                }

                return;
            }

            var clusterServiceUri = "http://localhost:" + args[3] + "/Services/Cluster";
            var localSearchServiceUri = "http://localhost:" + args[2] + "/Services/FlightSearch";

            var remoteSearchServiceUri = args[4];
            if (!remoteSearchServiceUri.StartsWith("http://"))
            {
                remoteSearchServiceUri = "http://" + remoteSearchServiceUri;
            }

            var cm = new ClusterManager(fdb, args[1], args[0], clusterServiceUri, localSearchServiceUri, remoteSearchServiceUri);

            var cs = new ClusterService(cm, fdb);

            try
            {
                if (log.IsInfoEnabled)
                {
                    log.Info("Starting cluster service on " + clusterServiceUri);
                }

                var host = new ServiceHost(cs, new Uri(clusterServiceUri));
                host.Open();

                if (log.IsDebugEnabled)
                {
                    log.Info("... OK");
                }
            }
            catch (Exception e)
            {
                if (log.IsFatalEnabled)
                {
                    log.Fatal("... Failed", e);
                }

                return;
            }

            try
            {
                if (log.IsInfoEnabled)
                {
                    log.Info("Starting cluster manager...");
                }

                string zkConnectionString;
                using (var reader = new StreamReader("zookeeper.conf"))
                {
                    zkConnectionString = reader.ReadLine();
                }

                cm.Start(zkConnectionString);

                if (log.IsInfoEnabled)
                {
                    log.Info("... OK");
                }
            }
            catch (Exception e)
            {
                if (log.IsFatalEnabled)
                {
                    log.Fatal("... Failed", e);
                }

                return;
            }

            if (log.IsInfoEnabled)
            {
                log.Info("Running...");
            }

            Console.WriteLine("Press ENTER to exit");
            Console.ReadLine();

            if (log.IsInfoEnabled)
            {
                log.Info("Stopping...");
            }

            cm.Dispose();
        }
    }
}
